package com.nineclock.approve.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.nineclock.approve.nodeResolver.ProcessNodeResolver;
import com.nineclock.approve.nodeResolver.factory.ProcessNodeResolverFactory;
import com.nineclock.approve.pojo.ApproveDefinition;
import com.nineclock.approve.service.ActivitiService;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Process;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Service
@Slf4j
public class ActivitiServiceImpl implements ActivitiService {

    @Autowired
    RepositoryService repositoryService;

    @Override
    public void deployProcessToActiviti(ApproveDefinition definition) {
        //创建 bpmnModel对象
        BpmnModel bpmnModel = new BpmnModel();
        //创建流程对象
        Process process = new Process();
        process.setId("process_" + definition.getId());
        process.setName(definition.getName());

        //获取流程json
        String flowJson = definition.getFlowJson();
        // 把流程json转换为 json数组
        JSONArray jsonArray = JSONUtil.parseArray(flowJson);

        addNodesToProcess(process, jsonArray);


        //添加流程到bpmnModel中
        bpmnModel.addProcess(process);

        //5. 自动布局BpmnModel
        new BpmnAutoLayout(bpmnModel).execute();


        //输出XML, 便于测试
        BpmnXMLConverter converter = new BpmnXMLConverter();
        byte[] bytes = converter.convertToXML(bpmnModel);

        log.info("-------> 转换BpmnModel为XML数据 .");
        System.out.println(new String(bytes));
        log.info("-------> XML文件转换并输出完毕 . ");

        //部署流程到 activiti中
        repositoryService
                .createDeployment()
                .name(definition.getName())
                .addBpmnModel(definition.getName() + ".bpmn", bpmnModel)
                .deploy();
    }

    @Override
    public void dropProcessFromActiviti(ApproveDefinition definition) {
        //根据 流程定义key 获取 流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("process_" + definition.getId()).singleResult();

        //根据部署id删除 流程定义
        repositoryService.deleteDeployment(processDefinition.getDeploymentId());
    }

    private void addNodesToProcess(Process process, JSONArray jsonArray) {

        if(jsonArray != null && jsonArray.size() > 0){
            for (int i = 0; i < jsonArray.size(); i ++) {
                //获取当前节点
                JSONObject currNode = (JSONObject) jsonArray.get(i);
                JSONObject nextNode = null;
                if(i < jsonArray.size() - 1){
                    //获取下一个节点
                    nextNode = (JSONObject) jsonArray.get(i + 1);
                }
                //获取当前节点的类型
                String type = currNode.getStr("type");
                //获取 对应的解析器
                ProcessNodeResolver nodeResolver = ProcessNodeResolverFactory.getInstance(type);
                //添加节点到 流程中
                nodeResolver.addFlowNodeToActiviti(process, currNode, nextNode);
            }
        }

    }
}
